import requests
import re
import time
from lxml import etree


class EmuchCracker(object):
    """实现小木虫论坛自动登录
    """
    def __init__(self, user_name, password):
        self.username = user_name
        self.password = password
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36'
        }
        self.start_url = "http://muchong.com/bbs/logging.php?action=login"
        self.session = requests.Session()

    def get_login_page(self):
        """发送GET请求,获取登录页面        
        Returns:
            [type] -- 登录页面解码之后的字符串
        """
        self.headers['Referer'] = "http://muchong.com/bbs"
        respons = self.session.get(url=self.start_url, headers=self.headers)
        return respons.content.decode('gbk')

    def parse_login_page(self, page_content):
        """解析第一个登录页面        
        Arguments:
            page_content GET请求获取到的登录页面解码后的字符串内容
        Returns:
            [type] -- 提取的到的post表单提交地址和表单提交所需信息
        """
        html = etree.HTML(page_content)
        first_post_url = 'http://muchong.com/bbs/' + html.xpath("//div[@class='user_info']/form/@action")[0]
        formhash = html.xpath("//div[@class='user_info']/form/input[@name='formhash']/@value")[0]
        cookie_time = html.xpath("//div[@class='user_info']/form//select/option[1]/@value")[0]
        login_submit = html.xpath("//div[@class='user_info']/form//input[@type='submit']/@value")[0]
        # 准备表单信息
        first_post_data = {
            'formhash': formhash,
            'username': self.username.encode('gbk'),
            'password': self.password,
            'cookietime': cookie_time,
            'refer': "",
            'loginsubmit': login_submit.encode('gbk')
        }

        return first_post_url, first_post_data

    def post_to_server(self, post_url, post_data):
        """获取post表单提交后的响应页面        
        Arguments:
            post_url {[str]} -- post表单提交地址
            post_data {[dict]} -- post表单提交数据        
        Returns:
            [type] -- 页面解码后的内容
        """
        respons = self.session.post(url=post_url, data=post_data, headers=self.headers)
        return respons.content.decode('gbk')
    
    def parse_first_post_content(self, page_content):
        """解析第一次POST请求之后的响应内容        
        Arguments:
            page_content {[str]} -- 页面解码之后的内容        
        Returns:
            [type] -- 第二次POST请求的地址和表单信息
        """
        html = etree.HTML(page_content)
        second_post_url = html.xpath("//div[@class='user_reg message']//form/@action")[0]
        second_post_formhash = html.xpath("//div[@class='user_reg message']//form//input[@name='formhash']/@value")[0]
        second_post_hash = html.xpath("//div[@class='user_reg message']//form//input[@name='post_sec_hash']/@value")[0]
        second_post_username = html.xpath("//div[@class='user_reg message']//form//input[@name='username']/@value")[0]
        second_post_login_submit = html.xpath("//div[@class='user_reg message']//form//input[@name='loginsubmit']/@value")[0]
        question = html.xpath("//div[@class='user_reg message']//form//div/text()")[0]

        regex = re.compile(r'问题：(\d+)(\w+)(\d+?)等于多少?')
        num_1 = regex.match(question).group(1)
        num_2 = regex.match(question).group(3)
        operator = regex.match(question).group(2)

        if re.match(r'加', operator):
            second_post_code = int(num_1) + int(num_2)
        elif re.match(r'减', operator):
            second_post_code = int(num_1) - int(num_2)
        elif re.match(r'除', operator):
            second_post_code = int(num_1) / int(num_2)
            second_post_code = int(second_post_code)
        elif re.match(r'乘', operator):
            second_post_code = int(num_1) * int(num_2)
        else:
            second_post_code = False

        second_post_data = {
            'formhash': second_post_formhash,
            'post_sec_code': second_post_code,
            'post_sec_hash': second_post_hash,
            'username': second_post_username.encode('gbk'),
            'loginsubmit': second_post_login_submit
        }

        return second_post_url, second_post_data

    def get_info_page(self):
        url = 'http://muchong.com/bbs/space.php?uid=751325'
        respon = self.session.get(url=url, headers=self.headers)
        return respon.content.decode('gbk')

    def run_spider(self):
        login_page_content = self.get_login_page()
        first_post_url, first_post_data = self.parse_login_page(login_page_content)
        first_post_content = self.post_to_server(first_post_url, first_post_data)
        second_post_url, second_post_data = self.parse_first_post_content(first_post_content)
        time.sleep(5)
        second_post_content = self.post_to_server(second_post_url, second_post_data)
        info_paget_content = self.get_info_page()
        with open('crack.html', 'w') as f:
            f.write(info_paget_content)
        print(self.session.cookies)


def main():
    crack_emuch = EmuchCracker('XXXXXX', 'XXXXXX')
    crack_emuch.run_spider()


if __name__ == '__main__':
    main()
